home *** CD-ROM | disk | FTP | other *** search
/ MPEG Toolkit / MPEG Toolkit.iso / os2 / mpegenc / src / readfram.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-01-01  |  17.0 KB  |  712 lines

  1. /*===========================================================================*
  2.  * readframe.c                                     *
  3.  *                                         *
  4.  *    procedures to read in frames                         *
  5.  *                                         *
  6.  * EXPORTED PROCEDURES:                                 *
  7.  *    ReadFrame                                 *
  8.  *    SetFileType                                 *
  9.  *    SetFileFormat                                 *
  10.  *                                         *
  11.  *===========================================================================*/
  12.  
  13. /*
  14.  * Copyright (c) 1993 The Regents of the University of California.
  15.  * All rights reserved.
  16.  *
  17.  * Permission to use, copy, modify, and distribute this software and its
  18.  * documentation for any purpose, without fee, and without written agreement is
  19.  * hereby granted, provided that the above copyright notice and the following
  20.  * two paragraphs appear in all copies of this software.
  21.  *
  22.  * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
  23.  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
  24.  * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
  25.  * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  26.  *
  27.  * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
  28.  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
  29.  * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
  30.  * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
  31.  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
  32.  */
  33.  
  34. /*  
  35.  *  $Header: /n/picasso/users/keving/encode/src/RCS/readframe.c,v 1.1 1993/07/22 22:23:43 keving Exp keving $
  36.  *  $Log: readframe.c,v $
  37.  * Revision 1.1  1993/07/22  22:23:43  keving
  38.  * nothing
  39.  *
  40.  */
  41.  
  42.  
  43. /*==============*
  44.  * HEADER FILES *
  45.  *==============*/
  46.  
  47. /* @@@ Fake up popen stuff */
  48. #ifdef OS2
  49. #include "os2port.h"
  50. #endif
  51. #include "all.h"
  52. #include <time.h>
  53. #include <errno.h>
  54. #include "mtypes.h"
  55. #include "frames.h"
  56. #ifdef OS2
  57. /* @@@ FAT 8.3 convention */
  58. #include "prototyp.h"
  59. #else
  60. #include "prototypes.h"
  61. #endif
  62. #include "parallel.h"
  63. #include "param.h"
  64. #ifdef OS2
  65. /* @@@ FAT 8.3 convention */
  66. #include "readfram.h"
  67. #else
  68. #include "readframe.h"
  69. #endif
  70. #include "fsize.h"
  71. #include "rgbtoycc.h"
  72.  
  73. #define PPM_READ_STATE_MAGIC    0
  74. #define PPM_READ_STATE_WIDTH    1
  75. #define PPM_READ_STATE_HEIGHT    2
  76. #define PPM_READ_STATE_MAXVAL    3
  77. #define PPM_READ_STATE_DONE    4
  78.  
  79.  
  80. /*==================*
  81.  * STATIC VARIABLES *
  82.  *==================*/
  83.  
  84. static int  fileType = BASE_FILE_TYPE;
  85. static int  baseFormat;
  86.  
  87.  
  88. /*===============================*
  89.  * INTERNAL PROCEDURE prototypes *
  90.  *===============================*/
  91.  
  92. static char *ScanNextString _ANSI_ARGS_((char *inputLine, char *string));
  93. static void ReadPNM _ANSI_ARGS_((FILE * fp, MpegFrame * mf));
  94. static boolean    ReadPPM _ANSI_ARGS_((MpegFrame *mf, FILE *fpointer));
  95. static void ReadYUV _ANSI_ARGS_((MpegFrame * mf, FILE *fpointer,
  96.                  int width, int height));
  97. static void ReadSub4 _ANSI_ARGS_((MpegFrame * mf, FILE *fpointer,
  98.                   int width, int height));
  99.  
  100.  
  101. /*=====================*
  102.  * EXPORTED PROCEDURES *
  103.  *=====================*/
  104.  
  105. /*===========================================================================*
  106.  *
  107.  * ReadFrame
  108.  *
  109.  *    reads the given frame, performing conversion as necessary
  110.  *    if addPath = TRUE, then must add the current path before the
  111.  *    file name
  112.  *
  113.  * RETURNS:    frame modified
  114.  *
  115.  * SIDE EFFECTS:    none
  116.  *
  117.  *===========================================================================*/
  118. void
  119. ReadFrame(frame, fileName, conversion, addPath)
  120.     MpegFrame *frame;
  121.     char *fileName;
  122.     char *conversion;
  123.     boolean addPath;
  124. {
  125.     FILE    *ifp;
  126.     char    command[1024];
  127.     char    fullFileName[1024];
  128. #ifdef BLEAH
  129.     static int32    readDiskTime = 0;
  130.     int32    diskStartTime, diskEndTime;
  131.  
  132. time(&diskStartTime);
  133. #endif
  134.  
  135.     if ( addPath ) {
  136.     sprintf(fullFileName, "%s/%s", currentPath, fileName);
  137.     } else {
  138.     sprintf(fullFileName, "%s", fileName);
  139.     }
  140.  
  141. #ifdef BLEAH
  142.     if ( ! childProcess ) {
  143.     fprintf(stdout, "+++++READING Frame %d  (type %d):  %s\n", frame->id,
  144.         frame->type, fullFileName);
  145.     }
  146. #endif
  147.  
  148.     if ( fileType == ANY_FILE_TYPE ) {
  149.     char *convertPtr, *commandPtr, *charPtr;
  150.  
  151.     /* replace every occurrence of '*' with fullFileName */
  152.     convertPtr = conversion;
  153.     commandPtr = command;
  154.     while ( *convertPtr != '\0' ) {
  155.         while ( (*convertPtr != '\0') && (*convertPtr != '*') ) {
  156.         *commandPtr = *convertPtr;
  157.         commandPtr++;
  158.         convertPtr++;
  159.         }
  160.  
  161.         if ( *convertPtr == '*' ) {
  162.         /* copy fullFileName */
  163.         charPtr = fullFileName;
  164.         while ( *charPtr != '\0' ) {
  165.             *commandPtr = *charPtr;
  166.             commandPtr++;
  167.             charPtr++;
  168.         }
  169.  
  170.         convertPtr++;   /* go past '*' */
  171.         }
  172.     }
  173.     *commandPtr = '\0';
  174.  
  175. /* @@@ Open binary mode for OS/2, Andy Key */
  176. #ifdef OS2
  177.     if ( (ifp = popen(command, "rb")) == NULL ) {
  178. #else
  179.     if ( (ifp = popen(command, "r")) == NULL ) {
  180. #endif
  181.         fprintf(stderr, "ERROR:  Couldn't execute input conversion command:\n");
  182.         fprintf(stderr, "\t%s\n", command);
  183.         fprintf(stderr, "errno = %d\n", errno);
  184.         if ( ioServer ) {
  185.         fprintf(stderr, "IO SERVER:  EXITING!!!\n");
  186.         } else {
  187.         fprintf(stderr, "SLAVE EXITING!!!\n");
  188.         }
  189.         exit(1);
  190.     }
  191.     } else {
  192. /* @@@ Open binary mode for OS/2, Andy Key */
  193. #ifdef OS2
  194.     if ( (ifp = fopen(fullFileName, "rb")) == NULL ) {
  195. #else
  196.     if ( (ifp = fopen(fullFileName, "r")) == NULL ) {
  197. #endif
  198.         fprintf(stderr, "ERROR:  Couldn't open input file %s\n",
  199.             fullFileName);
  200.         exit(1);
  201.     }
  202.     }
  203.  
  204.     switch(baseFormat) {
  205.     case YUV_FILE_TYPE:
  206.         ReadYUV(frame, ifp, realWidth, realHeight);
  207.         break;
  208.     case PPM_FILE_TYPE:
  209.         if ( ! ReadPPM(frame, ifp) ) {
  210.         fprintf(stderr, "Error reading PPM input file!!!\n");
  211.         exit(1);
  212.         }
  213.         PPMtoYUV(frame);
  214.         break;
  215.     case PNM_FILE_TYPE:
  216.         ReadPNM(ifp, frame);
  217.         PNMtoYUV(frame);
  218.         break;
  219.     case SUB4_FILE_TYPE:
  220.         ReadSub4(frame, ifp, yuvWidth, yuvHeight);
  221.         break;
  222.     default:
  223.         break;
  224.     }
  225.  
  226.     if ( fileType == ANY_FILE_TYPE ) {
  227.     pclose(ifp);
  228.     } else {
  229.     fclose(ifp);
  230.     }
  231.  
  232. #ifdef BLEAH
  233. time(&diskEndTime);
  234.  
  235.     readDiskTime += (diskEndTime-diskStartTime);
  236.  
  237. fprintf(stdout, "cumulative disk read time:  %d seconds\n", readDiskTime);
  238. #endif
  239.  
  240.     MotionSearchPreComputation(frame);
  241. }
  242.  
  243.  
  244. /*===========================================================================*
  245.  *
  246.  * SetFileType
  247.  *
  248.  *    set the file type to be either a base type (no conversion), or
  249.  *    any type (conversion required)
  250.  *
  251.  * RETURNS:    nothing
  252.  *
  253.  * SIDE EFFECTS:    fileType
  254.  *
  255.  *===========================================================================*/
  256. void
  257. SetFileType(conversion)
  258.     char *conversion;
  259. {
  260.     if ( strcmp(conversion, "*") == 0 ) {
  261.     fileType = BASE_FILE_TYPE;
  262.     } else {
  263.     fileType = ANY_FILE_TYPE;
  264.     }
  265. }
  266.  
  267.  
  268. /*===========================================================================*
  269.  *
  270.  * SetFileFormat
  271.  *
  272.  *    set the file format (PPM, PNM, YUV)
  273.  *
  274.  * RETURNS:    nothing
  275.  *
  276.  * SIDE EFFECTS:    baseFormat
  277.  *
  278.  *===========================================================================*/
  279. void
  280. SetFileFormat(format)
  281.     char *format;
  282. {
  283.     if ( strcmp(format, "PPM") == 0 ) {
  284.     baseFormat = PPM_FILE_TYPE;
  285.     } else if ( strcmp(format, "YUV") == 0 ) {
  286.     baseFormat = YUV_FILE_TYPE;
  287.     } else if ( strcmp(format, "PNM") == 0 ) {
  288.     baseFormat = PNM_FILE_TYPE;
  289.     } else if ( strcmp(format, "JPEG") == 0 ) {
  290.     fprintf(stderr, "SORRY:  JPEG not available YET\n");
  291.     exit(1);
  292.     } else if ( strcmp(format, "SUB4") == 0 ) {
  293.     baseFormat = SUB4_FILE_TYPE;
  294.     } else {
  295.     fprintf(stderr, "ERROR:  Invalid file format:  %s\n", format);
  296.     exit(1);
  297.     }
  298. }
  299.  
  300.  
  301. /*===========================================================================*
  302.  *
  303.  * ReadPNM
  304.  *
  305.  *    read a PNM file
  306.  *
  307.  * RETURNS:    mf modified
  308.  *
  309.  * SIDE EFFECTS:    none
  310.  *
  311.  *===========================================================================*/
  312. static void
  313. ReadPNM(fp, mf)
  314.     FILE *fp;
  315.     MpegFrame *mf;
  316. {
  317.     int x, y;
  318.     xelval maxval;
  319.     int format;
  320.  
  321.     mf->rgb_data = pnm_readpnm(fp, &x, &y, &maxval, &format);
  322.     ERRCHK(mf, "pnm_readpnm");
  323.  
  324.     if (format != PPM_FORMAT) {
  325.     if (maxval < 255) {
  326.         pnm_promoteformat(mf->rgb_data, x, y, maxval, format, 255, PPM_FORMAT);
  327.         maxval = 255;
  328.     } else {
  329.         pnm_promoteformat(mf->rgb_data, x, y, maxval, format, maxval, PPM_FORMAT);
  330.     }
  331.     }
  332.     if (maxval < 255) {
  333.     pnm_promoteformat(mf->rgb_data, x, y, maxval, format, 255, format);
  334.     maxval = 255;
  335.     }
  336.     /*
  337.      * if this is the first frame read, set the global frame size
  338.      */
  339.     Fsize_Note(mf->id, x, y);
  340.  
  341.     mf->rgb_maxval = maxval;
  342.     mf->rgb_format = PPM_FORMAT;
  343. }
  344.  
  345.  
  346.  
  347. /*===========================================================================*
  348.  *
  349.  * ReadIOConvert
  350.  *
  351.  *    do conversion; return a pointer to the appropriate file
  352.  *
  353.  * RETURNS:    pointer to the appropriate file
  354.  *
  355.  * SIDE EFFECTS:    none
  356.  *
  357.  *===========================================================================*/
  358. FILE *
  359. ReadIOConvert(fileName)
  360.     char *fileName;
  361. {
  362.     FILE    *ifp;
  363.     char    command[1024];
  364.     char    fullFileName[1024];
  365.     char *convertPtr, *commandPtr, *charPtr;
  366.  
  367.     sprintf(fullFileName, "%s/%s", currentPath, fileName);
  368.  
  369. #ifdef BLEAH
  370.     if ( ! childProcess ) {
  371.     fprintf(stdout, "+++++READING (IO CONVERT) Frame %d  (type %d):  %s\n", frame->id,
  372.         frame->type, fullFileName); }
  373. #endif
  374.  
  375.     if ( strcmp(ioConversion, "*") == 0 ) {
  376. /* @@@ Open binary mode for OS/2, Andy Key */
  377. #ifdef OS2
  378.     ifp = fopen(fullFileName, "rb");
  379. #else
  380.     ifp = fopen(fullFileName, "r");
  381. #endif
  382.  
  383.     ERRCHK(ifp, "fopen");
  384.  
  385.     return ifp;
  386.     }
  387.  
  388.     /* replace every occurrence of '*' with fullFileName */
  389.     convertPtr = ioConversion;
  390.     commandPtr = command;
  391.     while ( *convertPtr != '\0' ) {
  392.     while ( (*convertPtr != '\0') && (*convertPtr != '*') ) {
  393.         *commandPtr = *convertPtr;
  394.         commandPtr++;
  395.         convertPtr++;
  396.     }
  397.  
  398.     if ( *convertPtr == '*' ) {
  399.         /* copy fullFileName */
  400.         charPtr = fullFileName;
  401.         while ( *charPtr != '\0' ) {
  402.         *commandPtr = *charPtr;
  403.         commandPtr++;
  404.         charPtr++;
  405.         }
  406.  
  407.         convertPtr++;   /* go past '*' */
  408.     }
  409.     }
  410.     *commandPtr = '\0';
  411.  
  412. /* @@@ Open binary mode for OS/2, Andy Key */
  413. #ifdef OS2
  414.     if ( (ifp = popen(command, "rb")) == NULL ) {
  415. #else
  416.     if ( (ifp = popen(command, "r")) == NULL ) {
  417. #endif
  418.     fprintf(stderr, "ERROR:  Couldn't execute input conversion command:\n");
  419.     fprintf(stderr, "\t%s\n", command);
  420.     fprintf(stderr, "errno = %d\n", errno);
  421.     if ( ioServer ) {
  422.         fprintf(stderr, "IO SERVER:  EXITING!!!\n");
  423.     } else {
  424.         fprintf(stderr, "SLAVE EXITING!!!\n");
  425.     }
  426.     exit(1);
  427.     }
  428.  
  429.     return ifp;
  430. }
  431.  
  432.  
  433.  
  434. /*===========================================================================*
  435.  *
  436.  * ReadPPM
  437.  *
  438.  *    read a PPM file
  439.  *
  440.  * RETURNS:    TRUE if successful; FALSE otherwise; mf modified
  441.  *
  442.  * SIDE EFFECTS:    none
  443.  *
  444.  *===========================================================================*/
  445. static boolean
  446. ReadPPM(mf, fpointer)
  447.     MpegFrame *mf;
  448.     FILE *fpointer;
  449. {
  450.     char    inputBuffer[71];
  451.     char    string[71];
  452.     char    *inputLine;
  453.     int        height = 0, width = 0, maxVal;
  454.     uint8   junk[4096];
  455.     register int y;
  456.     int        state;
  457.  
  458.     state = PPM_READ_STATE_MAGIC;
  459.  
  460.     while ( state != PPM_READ_STATE_DONE ) {
  461.     if ( fgets(inputBuffer, 71, fpointer) == NULL ) {
  462.         return FALSE;
  463.     }
  464.     
  465.         inputLine = inputBuffer;
  466.  
  467.     if ( inputLine[0] == '#' ) {
  468.         continue;
  469.     }
  470.  
  471.     if ( inputLine[strlen(inputLine)-1] != '\n' ) {
  472.         return FALSE;
  473.     }
  474.  
  475.     switch(state) {
  476.         case PPM_READ_STATE_MAGIC:
  477.             if ( (inputLine = ScanNextString(inputLine, string)) == NULL ) {
  478.             return FALSE;
  479.         }
  480.  
  481.         if ( strcmp(string, "P6") != 0 ) {
  482.             return FALSE;
  483.         }
  484.         state = PPM_READ_STATE_WIDTH;
  485.         /* no break */
  486.         case PPM_READ_STATE_WIDTH:
  487.             if ( (inputLine = ScanNextString(inputLine, string)) == NULL ) {
  488.             if ( inputLine == inputBuffer ) {
  489.                 return FALSE;
  490.             } else {
  491.                 break;
  492.             }
  493.         }
  494.  
  495.         width = atoi(string);
  496.  
  497.         state = PPM_READ_STATE_HEIGHT;
  498.  
  499.         /* no break */
  500.         case PPM_READ_STATE_HEIGHT:
  501.             if ( (inputLine = ScanNextString(inputLine, string)) == NULL ) {
  502.             if ( inputLine == inputBuffer ) {
  503.                 return FALSE;
  504.             } else {
  505.                 break;
  506.             }
  507.         }
  508.  
  509.         height = atoi(string);
  510.  
  511.         state = PPM_READ_STATE_MAXVAL;
  512.  
  513.         /* no break */
  514.         case PPM_READ_STATE_MAXVAL:
  515.             if ( (inputLine = ScanNextString(inputLine, string)) == NULL ) {
  516.             if ( inputLine == inputBuffer ) {
  517.                 return FALSE;
  518.             } else {
  519.                 break;
  520.             }
  521.         }
  522.  
  523.         maxVal = atoi(string);
  524.  
  525.         state = PPM_READ_STATE_DONE;
  526.         break;
  527.     } /* end of switch */
  528.     }
  529.  
  530.     Fsize_Note(mf->id, width, height);
  531.  
  532.     mf->rgb_maxval = maxVal;
  533.  
  534.     Frame_AllocPPM(mf);
  535.  
  536.     for ( y = 0; y < Fsize_y; y++ ) {
  537.     fread(mf->ppm_data[y], sizeof(char), 3*Fsize_x, fpointer);
  538.  
  539.     /* read the leftover stuff on the right side */
  540.     fread(junk, sizeof(char), 3*(width-Fsize_x), fpointer);
  541.     }
  542.  
  543.     return TRUE;
  544. }
  545.  
  546.  
  547. /*===========================================================================*
  548.  *
  549.  * ReadYUV
  550.  *
  551.  *    read a YUV file
  552.  *
  553.  * RETURNS:    mf modified
  554.  *
  555.  * SIDE EFFECTS:    none
  556.  *
  557.  *===========================================================================*/
  558. static void
  559. ReadYUV(mf, fpointer, width, height)
  560.     MpegFrame *mf;
  561.     FILE *fpointer;
  562.     int width;
  563.     int height;
  564. {
  565.     register int y;
  566.     uint8   junk[4096];
  567.  
  568.     Fsize_Note(mf->id, width, height);
  569.  
  570.     Frame_AllocYCC(mf);
  571.  
  572.     for (y = 0; y < Fsize_y; y++) {            /* Y */
  573.     fread(mf->orig_y[y], 1, Fsize_x, fpointer);
  574.  
  575.     /* read the leftover stuff on the right side */
  576.     if ( width != Fsize_x ) {
  577.         fread(junk, 1, width-Fsize_x, fpointer);
  578.     }
  579.     }
  580.  
  581.     /* read the leftover stuff on the bottom */
  582.     for (y = Fsize_y; y < height; y++) {
  583.     fread(junk, 1, width, fpointer);
  584.     }
  585.  
  586.     for (y = 0; y < Fsize_y / 2; y++) {            /* U */
  587.     fread(mf->orig_cb[y], 1, Fsize_x / 2, fpointer);
  588.  
  589.     /* read the leftover stuff on the right side */
  590.     if ( width != Fsize_x ) {
  591.         fread(junk, 1, (width-Fsize_x)/2, fpointer);
  592.     }
  593.     }
  594.  
  595.     /* read the leftover stuff on the bottom */
  596.     for (y = Fsize_y / 2; y < height / 2; y++) {
  597.     fread(junk, 1, width/2, fpointer);
  598.     }
  599.  
  600.     for (y = 0; y < Fsize_y / 2; y++) {            /* V */
  601.     fread(mf->orig_cr[y], 1, Fsize_x / 2, fpointer);
  602.  
  603.     /* read the leftover stuff on the right side */
  604.     if ( width != Fsize_x ) {
  605.         fread(junk, 1, (width-Fsize_x)/2, fpointer);
  606.     }
  607.     }
  608.  
  609.     /* ignore leftover stuff on the bottom */
  610. }
  611.  
  612.  
  613. /*===========================================================================*
  614.  *
  615.  * ReadSub4
  616.  *
  617.  *    read a YUV file (subsampled even further by 4:1 ratio)
  618.  *
  619.  * RETURNS:    mf modified
  620.  *
  621.  * SIDE EFFECTS:    none
  622.  *
  623.  *===========================================================================*/
  624. static void
  625. ReadSub4(mf, fpointer, width, height)
  626.     MpegFrame *mf;
  627.     FILE *fpointer;
  628.     int width;
  629.     int height;
  630. {
  631.     register int y;
  632.     register int x;
  633.     uint8   buffer[1024];
  634.  
  635.     Fsize_Note(mf->id, width, height);
  636.  
  637.     Frame_AllocYCC(mf);
  638.  
  639.     for (y = 0; y < height/2; y++) {            /* Y */
  640.     fread(buffer, 1, width/2, fpointer);
  641.     for ( x = 0; x < width/2; x++ ) {
  642.         mf->orig_y[2*y][2*x] = buffer[x];
  643.         mf->orig_y[2*y][2*x+1] = buffer[x];
  644.         mf->orig_y[2*y+1][2*x] = buffer[x];
  645.         mf->orig_y[2*y+1][2*x+1] = buffer[x];
  646.     }
  647.     }
  648.  
  649.     for (y = 0; y < height / 4; y++) {            /* U */
  650.     fread(buffer, 1, width/4, fpointer);
  651.     for ( x = 0; x < width/4; x++ ) {
  652.         mf->orig_cb[2*y][2*x] = buffer[x];
  653.         mf->orig_cb[2*y][2*x+1] = buffer[x];
  654.         mf->orig_cb[2*y+1][2*x] = buffer[x];
  655.         mf->orig_cb[2*y+1][2*x+1] = buffer[x];
  656.     }
  657.     }
  658.  
  659.     for (y = 0; y < height / 4; y++) {            /* V */
  660.     fread(buffer, 1, width/4, fpointer);
  661.     for ( x = 0; x < width/4; x++ ) {
  662.         mf->orig_cr[2*y][2*x] = buffer[x];
  663.         mf->orig_cr[2*y][2*x+1] = buffer[x];
  664.         mf->orig_cr[2*y+1][2*x] = buffer[x];
  665.         mf->orig_cr[2*y+1][2*x+1] = buffer[x];
  666.     }
  667.     }
  668. }
  669.  
  670.  
  671. /*=====================*
  672.  * INTERNAL PROCEDURES *
  673.  *=====================*/
  674.  
  675. /*===========================================================================*
  676.  *
  677.  * ScanNextString
  678.  *
  679.  *    read a string from a input line, ignoring whitespace
  680.  *
  681.  * RETURNS:    pointer to position in input line after string
  682.  *              NULL if all whitespace
  683.  *              puts string in 'string'
  684.  *
  685.  * SIDE EFFECTS:    file stream munched a bit
  686.  *
  687.  *===========================================================================*/
  688. static char *
  689. ScanNextString(inputLine, string)
  690.     char *inputLine;
  691.     char *string;
  692. {
  693.     /* skip whitespace */
  694.     while ( isspace(*inputLine) && (*inputLine != '\n') ) {
  695.         inputLine++;
  696.     }
  697.  
  698.     if ( *inputLine == '\n' ) {
  699.         return NULL;
  700.     }
  701.  
  702.     while ( (! isspace(*inputLine)) && (*inputLine != '\n') ) {
  703.         *string = *inputLine;
  704.     string++;
  705.     inputLine++;
  706.     }
  707.  
  708.     *string = '\0';
  709.  
  710.     return inputLine;
  711. }
  712.